<!-- 图片选择器 -->
<template>
    <div class="edit-image-wrap">
        <template v-if="type === 'image'">
            <div class="edit-image-btn">
                <div class="edit-image">
                    <div v-if="showLabel" class="edit-image-label">
                        {{ label }}
                    </div>

                    <el-tooltip
                        placement="top"
                        trigger="hover"
                        effect="light"
                        :disabled="!currentValue || !!preview"
                    >
                        <div class="edit-image-content" @click="show = true">
                            <el-image :src="currentValue" fit="fill" :style="{ width: `${size}px`, height: `${size}px` }">
                                <template #error>
                                    <el-icon :style="{ fontSize: `${size / 2}px` }"><icon-picture /></el-icon>
                                </template>
                            </el-image>
                        </div>
                        <template #content>
                            <div class="edit-image-actions">
                                <el-button size="small" text @click.stop="onConfirmSelectImage('')">删除</el-button>
                                <el-button size="small" type="primary" @click.stop="onOpenCropeImage(currentValue)">编辑</el-button>
                            </div>
                        </template>
                    </el-tooltip>
                </div>
            </div>
        </template>
        <template v-else>
            <div @click="show = true">
                <slot></slot>
            </div>
        </template>
        

        <el-dialog
            v-model="show"
            width="900px"
            append-to-body
            :close-on-click-modal="false"
            class="edit-image-dialog"
            @open="onOpen"
        >
            <el-tabs modelValue="my" @tab-click="() => {}" class="edit-image-tabs">
                <el-tab-pane label="我的图片" name="my">
                    <div class="edit-image-tab-pane">
                        <div class="pane-left">
                            <div class="add-btn" @click="onAddClassify">
                                <el-icon><icon-add /></el-icon>
                                添加分类
                            </div>
                            <el-scrollbar height="100%">
                                <div v-infinite-scroll="onLoadClassify">
                                    <el-menu :default-active="selectCategory" @select="onSelectCategory">
                                        <template v-for="(item, index) in categoryList">
                                            <el-menu-item :index="item.id" class="image-category-item">
                                                <el-text truncated class="image-category-item-title">
                                                    {{ item.name }}
                                                </el-text>
                                                <div v-if="!!item.id" class="image-category-item-action">
                                                    <el-icon title="修改名称" @click.stop="onSetImgCategoryName(item)"><icon-edit-outline /></el-icon>
                                                    <el-icon title="删除" @click.stop="onDeleteImgCategory(item)"><icon-delete /></el-icon>
                                                </div>
                                            </el-menu-item>
                                        </template>
                                    </el-menu>
                                    <el-divider>没有更多了</el-divider>
                                </div>
                            </el-scrollbar>
                        </div>
                        <div class="pane-content">
                            <div class="pane-content-header">
                                <template v-if="!editImageStatus">
                                     <div class="edit-btn" @click="onEdit">
                                        <el-icon><icon-edit-outline /></el-icon>
                                        管理
                                    </div>
                                </template>
                                <template v-else>
                                    <div class="header-edit">
                                        <div class="header-edit-left">
                                            <el-checkbox
                                                :modelValue="allSelectStatus"
                                                label="全选"
                                                @change="onEditAllSelect"
                                            />
                                        </div>
                                        <div class="header-edit-right">
                                            <div>已选择 {{ Object.keys(selectImages).length }} 张图片</div>
                                            <div class="delete-btn" @click="onEditDelete">
                                                <el-icon><icon-delete /></el-icon>
                                                删除
                                            </div>
                                            <div class="save-btn" @click="onEditSave">完成</div>
                                        </div>
                                    </div>
                                </template>
                            </div>

                            <el-scrollbar
                                v-loading="loading"
                                element-loading-text="加载中..."
                                height="100%"
                            >
                                <div
                                    v-infinite-scroll="onLoadImage"
                                    :infinite-scroll-immediate="false"
                                    class="pane-content-list"
                                >
                                    <div v-if="!editImageStatus" class="upload-btn">
                                        <input type="file" accept="image/*" multiple class="upload-btn-input" @change="onAddImage" />
                                        <el-icon><icon-plus /></el-icon>
                                    </div>
                                    
                                    <template v-for="(item, index) in imageList">
                                        <div
                                            class="image-item"
                                            :class="{
                                                'edit': editImageStatus,
                                                'active': selectImages[item.id] && editImageStatus
                                            }"
                                            @click="onSelectImage(item.id)"
                                        >
                                            <el-checkbox
                                                v-if="editImageStatus"
                                                :modelValue="selectImages[item.id]"
                                                class="image-item-checkbox"
                                            />
                                            <div class="image-item-actions" @click.stop="onDeleteImage([item.id])">
                                                <el-icon><icon-delete /></el-icon>
                                            </div>
                                            <el-image
                                                v-if="editImageStatus"
                                                :src="item.url"
                                                fit="fill"
                                            ></el-image>
                                            <el-image
                                                v-else-if="preview"
                                                :src="item.url"
                                                :preview-src-list="imageList.map(n => n.url)"
                                                :initial-index="index"
                                                fit="fill"
                                            ></el-image>
                                            <el-image
                                                v-else
                                                :src="item.url"
                                                fit="fill"
                                                @click="onViewImage(item)"
                                            ></el-image>
                                        </div>
                                    </template>
                                </div>
                                <el-divider v-if="loading">加载中...</el-divider>
                                <el-divider v-if="!!isMore && !loading" style="cursor: pointer;" @click="onLoadImage">加载更多</el-divider>
                                <el-divider v-if="!isMore && imageList.length > 0 && !loading">没有更多了</el-divider>
                                <el-divider v-if="imageList.length === 0 && !loading && !isMore">暂无图片</el-divider>
                            </el-scrollbar>
                        </div>
                    </div>
                </el-tab-pane>
            </el-tabs>
        </el-dialog>

        <image-cropper-dialog
            v-model:visible="showImageCropper"
            :url="cropperImage"
            @crope="onConfirmCropeImage"
            @confirm="onConfirmSelectImage"
        />
    </div>
</template>

<script>
import { defineComponent, toRefs, ref, computed, nextTick } from 'vue'
import { useUserStore } from '@/store'
import { ElMessageBox, ElMessage } from 'element-plus'
import { getImgCategoryList, deleteImgCategory, updateImgCategoryName, getImgList, saveImgCategory, deleteImg, uploadImg } from '@/api/app'
import { randomStr } from '@/libs/tools'
import ImageCropperDialog from './components/image-cropper-dialog'
export default defineComponent({
    name: 'ImagePicker',
    components: {
        ImageCropperDialog
    },
    props: {
        modelValue: {
            type: String,
            default: ''
        },
        // 标题
        label: {
            type: String,
            default: '背景图'
        },
        // 类型(image图片、custom自定义)
        type: {
            type: String,
            default: 'image'
        },
        // 图片大小，当type = image时有效，默认32px
        size: {
            type: Number,
            default: 32
        },
        // 显示标题，type = image时有效
        showLabel: {
            type: Boolean,
            default: true
        },
        // 上传最大值，默认2MB
        uploadMaxSize: {
            type: Number,
            default: 2
        },
        // 预览模式，不可编辑
        preview: {
            type: Boolean,
            default: false
        },
        // 是否加上url()
        addUrl: {
            type: Boolean,
            default: false
        }
    },
    emits: [
        'update:modelValue'
    ],
    setup(props, { emit }) {
        const { modelValue, label, type, size, showLabel, uploadMaxSize, preview, addUrl } = toRefs(props)
        
        const userStore = useUserStore()

        const show = ref(false)

        const categoryList = ref([])
        const selectCategory = ref('')

        const editImageStatus = ref(false)
        const imageList = ref([])
        const selectImages = ref({})
        const page = ref(1)
        const pageSize = ref(50)
        const isMore = ref(true)
        const loading = ref(false)

        const showImageCropper = ref(false)
        const cropperImage = ref('')

        const userId = computed(() => userStore.userId)

        const currentValue = computed({
            get: () => {
                let value = modelValue.value
                if (addUrl.value) {
                    value = value.replace('url(','').replace(')','')
                }
                return value
            },
            set: val => {
                let value = val
                if (addUrl.value) {
                    value = `url(${val})`
                }
                emit('update:modelValue', value)
            }
        })

        const allSelectStatus = computed(() => imageList.value.every(item => selectImages.value[item.id] ))

        // 图片弹窗打开触发
        const onOpen = () => {
            init()
        }

        const init = () => {
            getCategorys().then(() => {
                nextTick(() => {
                    const activeId = categoryList.value?.[0]?.id || ''
                    onSelectCategory(activeId)
                })
            })
        }
        
        // 获取分类列表
        const getCategorys = () => {
            return new Promise((resolve, reject) => {
                getImgCategoryList().then(res => {
                    if (res.Status === 1) {
                        const list = res.Data || []
                        categoryList.value = list.map(item => ({
                            id: item.Id,
                            name: item.Name
                        }))
                        categoryList.value.unshift({
                            id: '',
                            name: '全部'
                        })
                        resolve()
                    }
                })
            })
        }
        // 添加图片分类
        const onAddClassify = () => {
            ElMessageBox.prompt('请输入分类名', '添加分类', {
                inputValue: '分类名',
                inputValidator: value => value !== '',
                inputErrorMessage: '分类名不能为空',
            }).then(({ value }) => {
                saveImgCategory(value).then(res => {
                    if (res.Status == 1) {
                        ElMessage({
                            type: 'success',
                            message: '添加分类成功'
                        })
                        getCategorys()
                    } else {
                        ElMessage({
                            type: 'warning',
                            message: '添加分类失败'
                        })
                    }
                })
            }).catch(() => {})
        }
        // 选择图片分类
        const onSelectCategory = id => {
            selectCategory.value = id
            page.value = 1
            isMore.value = true
            imageList.value = []
            getImages()
        }
        // 删除图片分类
        const onDeleteImgCategory = data => {
            const { id, name } = data
            ElMessageBox.confirm(`确定删除选中图片分类 ${name}?`, '提示', {
                type: 'warning',
            }).then(() => {
                loading.value = true
                deleteImgCategory(id)
                    .then(res => {
                        if (res.Status === 1) {
                            ElMessage({
                                type: 'success',
                                message: '删除图片分类成功'
                            })
                            init()
                        } else {
                            ElMessage({
                                type: 'warning',
                                message: '删除图片分失败'
                            })
                        }
                    })
                    .finally(() => {
                        loading.value = false
                    })
            }).catch(() => {})
        }
        // 修改图片分类名称
        const onSetImgCategoryName = data => {
            const { id, name } = data
            ElMessageBox.prompt('请输入分类名', '修改分类名', {
                inputValue: name,
                inputValidator: value => value !== '',
                inputErrorMessage: '分类名不能为空',
            }).then(({ value }) => {
                loading.value = true
                updateImgCategoryName({
                    id,
                    name: value
                }).then(res => {
                    if (res.Status == 1) {
                        ElMessage({
                            type: 'success',
                            message: '修改分类名成功'
                        })
                        getCategorys()
                    } else {
                        ElMessage({
                            type: 'warning',
                            message: '修改分类名失败'
                        })
                    }
                }).finally(() => {
                    loading.value = false
                })
            }).catch(() => {})
        }
        // 加载更多分类
        const onLoadClassify = () => {
            // console.log('加载分类')
        }

        // 获取图片列表
        const getImages = () => {
            loading.value = true
            getImgList({
                id: selectCategory.value,
                page: page.value,
                pageSize: pageSize.value
            }).then(res => {
                if (res.Status == 1) {
                    const data = res.Data
                    const list = data?.records || []
                    imageList.value.push(...list.map(item => ({
                        id: item.Id,
                        url: item.URL
                    })))
                    if (data.page >= data['total_page']) {
                        isMore.value = false
                    }
                }
            }).finally(() => {
                loading.value = false
            })
        }
        // 加载更多图片
        const onLoadImage = () => {
            if (!isMore.value && !loading.value) return
            page.value += 1
            getImages()
        }

        // 管理编辑
        const onEdit = () => {
            editImageStatus.value = true
        }
        // 完成编辑
        const onEditSave = () => {
            editImageStatus.value = false
            selectImages.value = {}
        }
        // 编辑全选
        const onEditAllSelect = value => {
            if (allSelectStatus.value) {
                selectImages.value = {}
            } else {
                selectImages.value = {}
                imageList.value.forEach(item => {
                    selectImages.value[item.id] = true
                })
            }
        }
        // 编辑删除
        const onEditDelete = () => {
            onDeleteImage(Object.keys(selectImages.value))
        }
        // 添加图片
        const onAddImage = e => {
            const files = Array.from(e.target.files)
            const maxSize = uploadMaxSize.value
            if (files.some(file => file.size > maxSize * 1024 * 1024)) {
                ElMessage({
                    type: 'warning',
                    message: `上传图片不能超过${maxSize}MB（${maxSize * 1024}KB）`
                })
                return
            }
            const requestList = files.map(file => onUploadImage(file))
            loading.value = true
            Promise.all(requestList).then(result => {
                onSelectCategory(selectCategory.value)
                if (result.length === files.length) {
                    ElMessage({
                        type: 'success',
                        message: '上传成功'
                    })
                } else {
                    ElMessage({
                        type: 'warning',
                        message: '部分图片未上传成功'
                    })
                }
            }).finally(() => {
                loading.value = false
            })
        }
        // 选择图片
        const onSelectImage = id => {
            if (selectImages.value[id]) {
                delete selectImages.value[id]
            } else {
                selectImages.value[id] = true
            }
        }
        // 查看指定图片
        const onViewImage = data => {
            onOpenCropeImage(data.url)
        }
        // 删除指定图片
        const onDeleteImage = ids => {
            ElMessageBox.confirm('确定删除选中图片?', '提示', {
                type: 'warning',
            }).then(() => {
                const requestList = ids.map(id => new Promise((resolve, reject) => {
                    deleteImg(id).then(res => {
                        if (res.Status === 1) {
                            resolve(id)
                        } else {
                            reject(id)
                        }
                    })
                }))
                loading.value = true
                Promise.all(requestList).then(result => {
                    result.forEach(id => {
                        const index = imageList.value.findIndex(item => item.id === id)
                        if (index !== -1) {
                            imageList.value.splice(index, 1)
                            delete selectImages.value[id]
                        }
                    })
                    if (result.length === ids.length) {
                        ElMessage({
                            type: 'success',
                            message: '删除图片成功'
                        })
                    } else {
                        ElMessage({
                            type: 'warning',
                            message: '部分图片未删除成功'
                        })
                    }
                }).finally(() => {
                    loading.value = false
                })
            }).catch(() => {})
        }

        // 上传图片
        const onUploadImage = file => {
            return new Promise((resolve, reject) => {
                uploadImg({
                    id: selectCategory.value,
                    memberId: userId.value,
                    file: file
                }).then(res => {
                    if (res.Status == 1) {
                        resolve(res.Data)
                    } else {
                        reject(res)
                    }
                }).catch(err => {
                    reject(err)
                })
            })
        }

        // 打开裁剪图片弹窗
        const onOpenCropeImage = url => {
            cropperImage.value = url
            showImageCropper.value = true
        }
        // 确认图片裁剪回调函数
        const onConfirmCropeImage = blob => {
            // blob 类型转换 file 类型
            const file = new File([blob], `${randomStr()}.${blob.type.split('/')[1]}`, { type: blob.type })
            // 将剪裁后的图片上传
            onUploadImage(file).then(res => {
                currentValue.value = res.url
                showImageCropper.value = false
                show.value = false
            }).catch(() => {
                ElMessage({
                    type: 'warning',
                    message: '裁剪失败，图片保存失败'
                })
            })
        }
        // 确认选择图片
        const onConfirmSelectImage = url => {
            currentValue.value = url
            show.value = false
        }

        return {
            label,
            type,
            size,
            showLabel,
            preview,

            show,

            currentValue,

            categoryList,
            selectCategory,

            editImageStatus,
            imageList,
            selectImages,
            allSelectStatus,
            isMore,
            loading,

            onOpen,
            onAddClassify,
            onDeleteImgCategory,
            onSetImgCategoryName,

            showImageCropper,
            cropperImage,

            onLoadClassify,
            onSelectCategory,
            onLoadImage,
            
            onEdit,
            onEditSave,
            onEditAllSelect,
            onEditDelete,
            onAddImage,
            onSelectImage,
            onViewImage,
            onDeleteImage,

            onOpenCropeImage,
            onConfirmCropeImage,
            onConfirmSelectImage
        }
    }
})
</script>

<style lang="less">
@import './image-picker.less';
</style>